<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Java equals与hashCode的契约关系</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            min-height: 100vh;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .content-card {
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            transition: all 0.3s ease;
        }
        .content-card:hover {
            transform: translateY(-2px);
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
        }
        .code-block {
            background: #1e1e1e;
            color: #d4d4d4;
            border-radius: 12px;
            overflow: hidden;
            position: relative;
        }
        .code-block::before {
            content: 'Java';
            position: absolute;
            top: 10px;
            right: 15px;
            color: #858585;
            font-size: 12px;
            font-weight: 500;
        }
        .drop-cap {
            float: left;
            font-size: 4rem;
            line-height: 1;
            font-weight: 700;
            margin-right: 0.5rem;
            color: #667eea;
            font-family: 'Noto Serif SC', serif;
        }
        .section-number {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 32px;
            height: 32px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border-radius: 50%;
            font-weight: 600;
            margin-right: 12px;
            flex-shrink: 0;
        }
        .highlight-box {
            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
            color: white;
            padding: 1.5rem;
            border-radius: 12px;
            margin: 2rem 0;
            position: relative;
            overflow: hidden;
        }
        .highlight-box::before {
            content: '';
            position: absolute;
            top: -50%;
            right: -50%;
            width: 200%;
            height: 200%;
            background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
            animation: pulse 3s ease-in-out infinite;
        }
        @keyframes pulse {
            0%, 100% { transform: scale(0.8); opacity: 0.5; }
            50% { transform: scale(1.2); opacity: 0.8; }
        }
        .mermaid {
            display: flex;
            justify-content: center;
            margin: 2rem 0;
        }
        code {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 0.2rem 0.5rem;
            border-radius: 4px;
            font-size: 0.9rem;
            font-weight: 500;
        }
        .list-item {
            position: relative;
            padding-left: 2rem;
            margin-bottom: 1rem;
        }
        .list-item::before {
            content: '\f00c';
            font-family: 'Font Awesome 6 Free';
            font-weight: 900;
            position: absolute;
            left: 0;
            color: #667eea;
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <div class="hero-gradient text-white py-20 px-6">
        <div class="max-w-6xl mx-auto text-center">
            <h1 class="text-5xl md:text-6xl font-bold mb-6 tracking-tight">
                <i class="fas fa-code mr-4"></i>Java equals与hashCode的契约关系
            </h1>
            <p class="text-xl md:text-2xl opacity-90 max-w-3xl mx-auto leading-relaxed">
                深入理解Java集合框架中的核心约定，掌握对象相等性判断的最佳实践
            </p>
        </div>
    </div>

    <!-- Main Content -->
    <div class="max-w-6xl mx-auto px-6 py-12">
        <!-- Introduction Card -->
        <div class="content-card rounded-2xl shadow-xl p-8 mb-8">
            <p class="text-lg leading-relaxed text-gray-700">
                <span class="drop-cap">在</span>Java中，如果你重写了<code>equals</code>方法，通常也需要重写<code>hashCode</code>方法，这主要是由于Java集合框架的工作原理和hash算法的性质。这种契约关系是Java编程中的基础概念，对于构建健壮的应用程序至关重要。
            </p>
        </div>

        <!-- Visual Diagram -->
        <div class="content-card rounded-2xl shadow-xl p-8 mb-8">
            <h2 class="text-2xl font-bold mb-6 text-gray-800 flex items-center">
                <i class="fas fa-diagram-project mr-3 text-purple-600"></i>
                核心概念关系图
            </h2>
            <div class="mermaid">
                graph TD
                    A[Object对象] --> B[equals方法]
                    A --> C[hashCode方法]
                    B --> D[判断对象相等性]
                    C --> E[返回哈希码]
                    D --> F[相等的对象]
                    E --> G[哈希表定位]
                    F --> H[必须有相同的hashCode]
                    G --> I[HashMap/HashSet等集合]
                    H --> I
                    style A fill:#667eea,stroke:#fff,stroke-width:3px,color:#fff
                    style F fill:#f093fb,stroke:#fff,stroke-width:3px,color:#fff
                    style H fill:#f5576c,stroke:#fff,stroke-width:3px,color:#fff
            </div>
        </div>

        <!-- Section 1 -->
        <div class="content-card rounded-2xl shadow-xl p-8 mb-8">
            <h3 class="text-2xl font-bold mb-6 text-gray-800 flex items-center">
                <span class="section-number">1</span>
                hashCode的基本概念
            </h3>
            <p class="text-lg leading-relaxed text-gray-700 mb-4">
                <code>hashCode</code>方法返回一个整数，作为对象的哈希码。Java集合（如<code>HashSet</code>, <code>HashMap</code>）使用哈希码来快速查找对象。哈希码用于确定对象在哈希表中的位置，以提高查找效率。
            </p>
            <div class="bg-purple-50 border-l-4 border-purple-600 p-4 rounded-r-lg">
                <p class="text-gray-700 flex items-start">
                    <i class="fas fa-lightbulb text-purple-600 mr-3 mt-1"></i>
                    <span>哈希码就像是对象的"邮政编码"，帮助集合快速定位对象的存储位置。</span>
                </p>
            </div>
        </div>

        <!-- Section 2 -->
        <div class="content-card rounded-2xl shadow-xl p-8 mb-8">
            <h3 class="text-2xl font-bold mb-6 text-gray-800 flex items-center">
                <span class="section-number">2</span>
                equals与hashCode的关系
            </h3>
            <p class="text-lg leading-relaxed text-gray-700">
                根据Java的约定，如果两个对象通过<code>equals</code>方法比较相等，那么这两个对象必须返回相同的<code>hashCode</code>。这条约定在Java文档中明确规定，确保了在使用基于哈希的集合时的一致性。
            </p>
        </div>

        <!-- Highlight Box -->
        <div class="highlight-box">
            <h3 class="text-2xl font-bold mb-4 flex items-center">
                <i class="fas fa-exclamation-triangle mr-3"></i>
                核心契约
            </h3>
            <p class="text-lg leading-relaxed relative z-10">
                如果 a.equals(b) == true，那么 a.hashCode() == b.hashCode() 必须成立！
            </p>
        </div>

        <!-- Section 3 -->
        <div class="content-card rounded-2xl shadow-xl p-8 mb-8">
            <h3 class="text-2xl font-bold mb-6 text-gray-800 flex items-center">
                <span class="section-number">3</span>
                为什么重写hashCode
            </h3>
            <div class="space-y-4">
                <div class="list-item">
                    <strong class="text-lg text-gray-800">避免数据丢失</strong>
                    <p class="text-gray-700 mt-2">如果重写了<code>equals</code>而未重写<code>hashCode</code>，当两个对象被认为相等时，它们的哈希码可能不同，这可能导致集合（如<code>HashSet</code>或<code>HashMap</code>）无法正确找到、存储或检索这些对象，从而引发数据丢失。</p>
                </div>
                <div class="list-item">
                    <strong class="text-lg text-gray-800">确保集合操作的正确性</strong>
                    <p class="text-gray-700 mt-2">当你将对象放入哈希集合中时，集合会使用<code>hashCode</code>来确定对象的位置。如果对象的哈希码不一致，即使对象被认为相等，它们可能会被存储在不同的位置，从而导致查找、更新或删除时出现问题。</p>
                </div>
            </div>
        </div>

        <!-- Code Example -->
        <div class="content-card rounded-2xl shadow-xl p-8 mb-8">
            <h3 class="text-2xl font-bold mb-6 text-gray-800 flex items-center">
                <span class="section-number">4</span>
                示例代码
            </h3>
            <p class="text-lg text-gray-700 mb-6">考虑以下示例，展示了正确重写equals和hashCode的方式：</p>
            <div class="code-block p-6">
                <pre class="text-sm md:text-base overflow-x-auto"><code>public class Person {
    private String name;
    private int age;

    // Constructor, getters, and setters

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Person)) return false;
        Person other = (Person) obj;
        return this.name.equals(other.name) && this.age == other.age;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}</code></pre>
            </div>
            <p class="text-gray-700 mt-6 bg-yellow-50 border-l-4 border-yellow-400 p-4 rounded-r-lg">
                <i class="fas fa-info-circle text-yellow-600 mr-2"></i>
                在这个例子中，如果我们只重写了<code>equals</code>方法而不重写<code>hashCode</code>，相同名称和年龄的<code>Person</code>对象在哈希集合中会被视为不同的对象，这将导致意外的行为。
            </p>
        </div>

        <!-- Best Practices -->
        <div class="content-card rounded-2xl shadow-xl p-8 mb-8">
            <h3 class="text-2xl font-bold mb-6 text-gray-800 flex items-center">
                <span class="section-number">5</span>
                实践建议
            </h3>
            <div class="grid md:grid-cols-2 gap-6">
                <div class="bg-gradient-to-br from-purple-50 to-pink-50 p-6 rounded-xl">
                    <h4 class="font-bold text-lg mb-3 flex items-center text-purple-800">
                        <i class="fas fa-check-circle mr-2"></i>
                        始终遵循约定
                    </h4>
                    <p class="text-gray-700">在重写<code>equals</code>时，应该总是重写<code>hashCode</code>，以保证遵循Java的合同。</p>
                </div>
                <div class="bg-gradient-to-br from-blue-50 to-cyan-50 p-6 rounded-xl">
                    <h4 class="font-bold text-lg mb-3 flex items-center text-blue-800">
                        <i class="fas fa-sync-alt mr-2"></i>
                        保持一致性
                    </h4>
                    <p class="text-gray-700">确保<code>hashCode</code>和<code>equals</code>的实现逻辑一致，即相等的对象应有相同的哈希码。</p>
                </div>
            </div>
        </div>

        <!-- Performance Considerations -->
        <div class="content-card rounded-2xl shadow-xl p-8">
            <h3 class="text-2xl font-bold mb-6 text-gray-800 flex items-center">
                